home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / nslookup / RCS / list.c,v < prev    next >
Encoding:
Text File  |  1988-11-27  |  19.7 KB  |  868 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     88.11.23.13.39.14;  author douglis;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @original src from monet.
  17. @
  18.  
  19.  
  20.  
  21. 1.1
  22. log
  23. @Initial revision
  24. @
  25. text
  26. @/*
  27.  * Copyright (c) 1985 Regents of the University of California.
  28.  * All rights reserved.
  29.  *
  30.  * Redistribution and use in source and binary forms are permitted
  31.  * provided that the above copyright notice and this paragraph are
  32.  * duplicated in all such forms and that any documentation,
  33.  * advertising materials, and other materials related to such
  34.  * distribution and use acknowledge that the software was developed
  35.  * by the University of California, Berkeley.  The name of the
  36.  * University may not be used to endorse or promote products derived
  37.  * from this software without specific prior written permission.
  38.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  39.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  40.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  41.  */
  42.  
  43. #ifndef lint
  44. static char sccsid[] = "@@(#)list.c    5.13 (Berkeley) 7/23/88";
  45. #endif /* not lint */
  46.  
  47. /*
  48.  *******************************************************************************
  49.  *
  50.  *  list.c --
  51.  *
  52.  *    Routines to obtain info from name and finger servers.
  53.  *
  54.  *    Adapted from 4.3BSD BIND ns_init.c and from /usr/src/ucb/finger.c
  55.  *
  56.  *******************************************************************************
  57.  */
  58.  
  59. #include <sys/types.h>
  60. #include <sys/socket.h>
  61. #include <netinet/in.h>
  62. #include <netdb.h>
  63. #include <stdio.h>
  64. #include <strings.h>
  65. #include <ctype.h>
  66. #include <arpa/nameser.h>
  67. #include <resolv.h>
  68. #include "res.h"
  69.  
  70. /*
  71.  *  Imported from res_debug.c
  72.  */
  73. extern char *_res_resultcodes[];
  74.  
  75. typedef union {
  76.     HEADER qb1;
  77.     char qb2[PACKETSZ];
  78. } querybuf;
  79.  
  80. extern u_long         inet_addr();
  81. extern HostInfo     *defaultPtr;
  82. extern HostInfo     curHostInfo;
  83. extern int         curHostValid;
  84.  
  85. /*
  86.  *  During a listing to a file, hash marks are printed 
  87.  *  every HASH_SIZE records.
  88.  */
  89.  
  90. #define HASH_SIZE 50
  91.  
  92.  
  93. /*
  94.  *******************************************************************************
  95.  *
  96.  *  ListHosts --
  97.  *
  98.  *    Requests the name server to do a zone transfer so we
  99.  *    find out what hosts it knows about.
  100.  *
  101.  *    There are five types of output:
  102.  *    - internet addresses (default)
  103.  *    - cpu type and operating system (-h option)
  104.  *    - canonical and alias names  (-a option)
  105.  *    - well-known service names  (-s option)
  106.  *    - ALL records (-d option)
  107.  *    
  108.  *    To see all three types of information in sorted order, 
  109.  *    do the following:
  110.  *      ls domain.edu > file
  111.  *      ls -a domain.edu >> file
  112.  *      ls -h domain.edu >> file
  113.  *      ls -s domain.edu >> file
  114.  *      view file
  115.  *
  116.  *  Results:
  117.  *    SUCCESS        the listing was successful.
  118.  *    ERROR        the server could not be contacted because 
  119.  *            a socket could not be obtained or an error
  120.  *            occured while receiving, or the output file
  121.  *            could not be opened.
  122.  *
  123.  *******************************************************************************
  124.  */
  125.  
  126. int
  127. ListHosts(string, putToFile)
  128.     char *string;
  129.     int  putToFile;
  130. {
  131.     querybuf         buf;
  132.     struct sockaddr_in     sin;
  133.     HEADER             *headerPtr;
  134.     int             queryType;
  135.     int             msglen;
  136.     int             amtToRead;
  137.     int             numRead;
  138.     int             i;
  139.     int             numAnswers = 0;
  140.     int             result;
  141.     int             soacnt = 0;
  142.     u_short         len;
  143.     char             *cp, *nmp;
  144.     char             name[NAME_LEN];
  145.     char             dname[2][NAME_LEN];
  146.     char             option[NAME_LEN];
  147.     char             file[NAME_LEN];
  148.     char            *namePtr;
  149.     static char        *answer = NULL;
  150.     static int        answerLen = 0;
  151.     enum {
  152.         NO_ERRORS, 
  153.         ERR_READING_LEN, 
  154.         ERR_READING_MSG,
  155.         ERR_PRINTING,
  156.     } error = NO_ERRORS;
  157.  
  158.     /*
  159.      *  Parse the command line. It maybe of the form "ls domain",
  160.      *  "ls -a domain" or "ls -h domain".
  161.      */ 
  162.     i = sscanf(string, " ls %s %s", option, name);
  163.     if (putToFile && i == 2 && name[0] == '>') {
  164.         i--;
  165.     }
  166.     if (i == 2) {
  167.         if (strcmp("-a", option) == 0) {
  168.         queryType = T_CNAME;
  169.         } else if (strcmp("-h", option) == 0) {
  170.         queryType = T_HINFO;
  171.         } else if (strcmp("-m", option) == 0) {
  172.         queryType = T_MX;
  173.         } else if (strcmp("-s", option) == 0) {
  174.         queryType = T_WKS;
  175.         } else if (strcmp("-d", option) == 0) {
  176.         queryType = T_ANY;
  177.         } else {
  178.         queryType = T_A;
  179.         }
  180.         namePtr = name;
  181.     } else if (i == 1) {
  182.         namePtr = option;
  183.         queryType = T_A;
  184.     } else {
  185.         fprintf(stderr, "ListHosts: invalid request %s\n",string);
  186.         return(ERROR);
  187.     }
  188.  
  189.  
  190.     /*
  191.      *  Create a query packet for the requested domain name.
  192.      */
  193.     msglen = res_mkquery(QUERY, namePtr, C_IN, T_AXFR,
  194.                 (char *)0, 0, (char *)0, 
  195.                 (char *) &buf, sizeof(buf));
  196.     if (msglen < 0) {
  197.         if (_res.options & RES_DEBUG) {
  198.         fprintf(stderr, "ListHosts: Res_mkquery failed\n");
  199.         }
  200.         return (ERROR);
  201.     }
  202.  
  203.     bzero((char *)&sin, sizeof(sin));
  204.     sin.sin_family    = AF_INET;
  205.     sin.sin_port    =  htons(NAMESERVER_PORT);
  206.  
  207.     /*
  208.      *  Check to see if we have the address of the server or the
  209.      *  address of a server who knows about this domain.
  210.      *       
  211.      *  For now, just use the first address in the list.
  212.      */
  213.  
  214.     if (defaultPtr->addrList != NULL) {
  215.       sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0];
  216.     } else {
  217.       sin.sin_addr = *(struct in_addr *)defaultPtr->servers[0]->addrList[0];
  218.     }
  219.  
  220.     /*
  221.      *  Set up a virtual circuit to the server.
  222.      */
  223.     if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  224.         perror("ListHosts");
  225.         return(ERROR);
  226.     }    
  227.     if (connect(sockFD, &sin, sizeof(sin)) < 0) {
  228.         perror("ListHosts");
  229.         (void) close(sockFD);
  230.         sockFD = -1;
  231.         return(ERROR);
  232.     }    
  233.  
  234.     /*
  235.      * Send length & message for zone transfer 
  236.      */
  237.  
  238.         len = htons(msglen);
  239.  
  240.         if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) ||
  241.             write(sockFD, (char *) &buf, msglen) != msglen) {
  242.         perror("ListHosts");
  243.         (void) close(sockFD);
  244.         sockFD = -1;
  245.         return(ERROR);
  246.     }
  247.  
  248.     fprintf(stdout,"[%s]\n",
  249.         (defaultPtr->addrList != NULL) ? defaultPtr->name : 
  250.          defaultPtr->servers[0]->name);
  251.  
  252.     if (!putToFile) {
  253.         filePtr = stdout;
  254.     } else {
  255.         filePtr = OpenFile(string, file);
  256.             if (filePtr == NULL) {
  257.                 fprintf(stderr, "*** Can't open %s for writing\n", file);
  258.         (void) close(sockFD);
  259.         sockFD = -1;
  260.                 return(ERROR);
  261.             }
  262.         fprintf(filePtr, "> %s\n", string);
  263.         fprintf(filePtr,"[%s]\n",
  264.         (defaultPtr->addrList != NULL) ? defaultPtr->name : 
  265.          defaultPtr->servers[0]->name);
  266.     }
  267.  
  268.     fprintf(filePtr, "%-30s", "Host or domain name");
  269.     switch(queryType) {
  270.         case T_ANY:
  271.             fprintf(filePtr, " %-30s\n", "Resource record info");
  272.             break;
  273.         case T_A:
  274.             fprintf(filePtr, " %-30s\n", "Internet address");
  275.             break;
  276.         case T_HINFO:
  277.             fprintf(filePtr, " %-10s %s\n", "CPU", "OS");
  278.             break;
  279.         case T_CNAME:
  280.             fprintf(filePtr, " %-30s\n", "Alias");
  281.             break;
  282.         case T_MX:
  283.             fprintf(filePtr, " %3s %s\n", "Metric", "Host");
  284.             break;
  285.         case T_WKS:
  286.             fprintf(filePtr, " %-4s %s\n", "Protocol", "Services");
  287.     }
  288.  
  289.  
  290.     while (1) {
  291.         unsigned short tmp;
  292.  
  293.         /*
  294.          * Read the length of the response.
  295.          */
  296.  
  297.         cp = (char *) &tmp;
  298.         amtToRead = sizeof(u_short);
  299.         while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
  300.         cp       += numRead;
  301.         amtToRead -= numRead;
  302.         }
  303.         if (numRead <= 0) {
  304.         error = ERR_READING_LEN;
  305.         break;
  306.         }    
  307.  
  308.         if ((len = htons(tmp)) == 0) {
  309.         break;    /* nothing left to read */
  310.         }
  311.  
  312.         /*
  313.          * The server sent too much data to fit the existing buffer --
  314.          * allocate a new one.
  315.          */
  316.         if (len > answerLen) {
  317.         if (answerLen != 0) {
  318.             free(answer);
  319.         }
  320.         answerLen = len;
  321.         answer = Malloc(answerLen);
  322.         }    
  323.  
  324.         /*
  325.          * Read the response.
  326.          */
  327.  
  328.         amtToRead = len;
  329.         cp = answer;
  330.         while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
  331.         cp += numRead;
  332.         amtToRead -= numRead;
  333.         }
  334.         if (numRead <= 0) {
  335.         error = ERR_READING_MSG;
  336.         break;
  337.         }
  338.  
  339.         result = PrintListInfo(filePtr, answer, cp, queryType);
  340.         if (result != SUCCESS) {
  341.         error = ERR_PRINTING;
  342.         break;
  343.         }
  344.  
  345.         numAnswers++;
  346.         if (putToFile && ((numAnswers % HASH_SIZE) == 0)) {
  347.         fprintf(stdout, "#");
  348.         fflush(stdout);
  349.         }
  350.         cp = answer + sizeof(HEADER);
  351.         if (ntohs(((HEADER* )answer)->qdcount) > 0)
  352.         cp += dn_skipname(cp, answer + len) + QFIXEDSZ;
  353.         nmp = cp;
  354.         cp += dn_skipname(cp, (u_char *)answer + len);
  355.         if ((_getshort(cp) == T_SOA)) {
  356.         dn_expand(answer, answer + len, nmp, dname[soacnt],
  357.             sizeof(dname[0]));
  358.             if (soacnt) {
  359.             if (strcmp(dname[0], dname[1]) == 0)
  360.             break;
  361.         } else
  362.             soacnt++;
  363.         }
  364.     }
  365.  
  366.     if (putToFile) {
  367.         fprintf(stdout, "%sReceived %d record%s.\n", 
  368.         (numAnswers >= HASH_SIZE) ? "\n" : "",
  369.         numAnswers,
  370.         (numAnswers != 1) ? "s" : "");
  371.     }
  372.  
  373.     (void) close(sockFD);
  374.     sockFD = -1;
  375.     if (putToFile) {
  376.         fclose(filePtr);
  377.         filePtr = NULL;
  378.     }
  379.  
  380.     switch (error) {
  381.         case NO_ERRORS:
  382.         return (SUCCESS);
  383.  
  384.         case ERR_READING_LEN:
  385.         return(ERROR);
  386.  
  387.         case ERR_PRINTING:
  388.         fprintf(stderr,"*** Error during listing of %s: %s\n", 
  389.                 namePtr, DecodeError(result));
  390.         return(result);
  391.  
  392.         case ERR_READING_MSG:
  393.         headerPtr = (HEADER *) answer;
  394.         fprintf(stderr,"ListHosts: error receiving zone transfer:\n");
  395.         fprintf(stderr,
  396.            "  result: %s, answers = %d, authority = %d, additional = %d\n", 
  397.                 _res_resultcodes[headerPtr->rcode], 
  398.                 ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), 
  399.             ntohs(headerPtr->arcount));
  400.         return(ERROR);
  401.         default:
  402.         return(ERROR);
  403.     }
  404. }
  405.  
  406.  
  407. /*
  408.  *******************************************************************************
  409.  *
  410.  *  PrintListInfo --
  411.  *
  412.  *     Used by the ListInfo routine to print the answer 
  413.  *    received from the name server. Only the desired 
  414.  *    information is printed.
  415.  *
  416.  *  Results:
  417.  *    SUCCESS        the answer was printed without a problem.
  418.  *    NO_INFO        the answer packet did not contain an answer.
  419.  *    ERROR        the answer was malformed.
  420.  *      Misc. errors    returned in the packet header.
  421.  *
  422.  *******************************************************************************
  423.  */
  424.  
  425. #define NAME_FORMAT " %-30s"
  426. #define STRIP_DOMAIN(string) if((dot = index(string, '.')) != NULL) *dot = '\0'
  427.  
  428.  
  429. PrintListInfo(file, msg, eom, queryType)
  430.     FILE     *file;
  431.     char     *msg, *eom;
  432.     int     queryType;
  433. {
  434.     register char     *cp;
  435.     HEADER         *headerPtr;
  436.     int         type, class, dlen, nameLen;
  437.     u_long        ttl;
  438.     int         n;
  439.     struct in_addr     inaddr;
  440.     char         name[NAME_LEN];
  441.     char         name2[NAME_LEN];
  442.     char         *dot;
  443.  
  444.     /*
  445.      * Read the header fields.
  446.      */
  447.     headerPtr = (HEADER *)msg;
  448.     cp = msg + sizeof(HEADER);
  449.     if (headerPtr->rcode != NOERROR) {
  450.     return(headerPtr->rcode);
  451.     }
  452.  
  453.     /*
  454.      *  We are looking for info from answer resource records.
  455.      *  If there aren't any, return with an error. We assume
  456.      *  there aren't any question records.
  457.      */
  458.  
  459.     if (ntohs(headerPtr->ancount) == 0) {
  460.     return(NO_INFO);
  461.     } else {
  462.     if (ntohs(headerPtr->qdcount) > 0) {
  463.         nameLen = dn_skipname(cp, eom);
  464.         if (nameLen < 0)
  465.         return (ERROR);
  466.         cp += nameLen + QFIXEDSZ;
  467.     }
  468.     if ((nameLen = dn_expand(msg, eom, cp, name, sizeof(name))) < 0) {
  469.         return (ERROR);
  470.     }
  471.     cp += nameLen;
  472.     type = _getshort(cp);
  473.     cp += sizeof(u_short);
  474.     class = _getshort(cp);
  475.     cp += sizeof(u_short);
  476.     ttl = _getlong(cp);
  477.     cp += sizeof(u_long);
  478.     dlen = _getshort(cp);
  479.     cp += sizeof(u_short);
  480.     if (name[0] == 0)
  481.         strcpy(name, "(root)");
  482.  
  483.     /*
  484.      * QueryType is used to specify the type of desired information.
  485.      *  T_A       - internet address
  486.      *  T_CNAME     - aliases
  487.      *  T_HINFO    - cpu, OS type
  488.      *  T_MX    - mail routing
  489.      *  T_WKS    - well known service
  490.      *  T_ANY    - any
  491.      *
  492.      */
  493.     switch (type) {
  494.  
  495.         case T_A:
  496.         if (queryType != T_A && queryType != T_ANY)
  497.             break;
  498.  
  499.         if ((_res.options & RES_DEBUG) == 0)
  500.             STRIP_DOMAIN(name);
  501.         fprintf(file, NAME_FORMAT, name);
  502.         if (queryType == T_ANY)
  503.             fprintf(file," %-5s", p_type(type));
  504.         if (class == C_IN) {
  505.             bcopy(cp, (char *)&inaddr, sizeof(inaddr));
  506.             if (dlen == 4) {
  507.             fprintf(file," %s", inet_ntoa(inaddr));
  508.             } else if (dlen == 7) {
  509.             fprintf(file," %s", inet_ntoa(inaddr));
  510.             fprintf(file," (%d, %d)", cp[4],(cp[5] << 8) + cp[6]);
  511.             } else
  512.             fprintf(file, " (dlen = %d?)", dlen);
  513.             if (_res.options & RES_DEBUG)
  514.             fprintf(file,"\t\t\t%lu", ttl);
  515.             fprintf(file,"\n");
  516.         } else
  517.             goto other;
  518.         break;
  519.         
  520.         case T_CNAME:
  521.         if (queryType != T_CNAME && queryType != T_ANY)
  522.             break;
  523.  
  524.         if ((_res.options & RES_DEBUG) == 0)
  525.             STRIP_DOMAIN(name);
  526.         fprintf(file, NAME_FORMAT, name);
  527.         if (queryType == T_ANY)
  528.             fprintf(file," %-5s", p_type(type));
  529.         if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
  530.             fprintf(file, " ***\n");
  531.             return (ERROR);
  532.         }
  533.         /* 
  534.          * a bug -- cnames need not be in same domain!
  535.          * STRIP_DOMAIN(name2);
  536.          */
  537.  
  538.         fprintf(file, NAME_FORMAT, name2);
  539.         if (_res.options & RES_DEBUG)
  540.             fprintf(file,"\t%lu", ttl);
  541.         fprintf(file,"\n");
  542.         break;
  543.         
  544.         case T_HINFO:
  545.         if (queryType != T_HINFO && queryType != T_ANY)
  546.             break;
  547.  
  548.         if ((_res.options & RES_DEBUG) == 0)
  549.             STRIP_DOMAIN(name);
  550.         fprintf(file, NAME_FORMAT, name);
  551.         if (queryType == T_ANY)
  552.             fprintf(file," %-5s", p_type(type));
  553.         if (n = *cp++) {
  554.             (void)sprintf(name,"%.*s", n, cp);
  555.             fprintf(file," %-10s", name);
  556.             cp += n;
  557.         } else {
  558.             fprintf(file," %-10s", " ");
  559.         }
  560.         if (n = *cp++) {
  561.             fprintf(file," %.*s", n, cp);
  562.             cp += n;
  563.         }
  564.         if (_res.options & RES_DEBUG)
  565.             fprintf(file,"\t\t%lu", ttl);
  566.         fprintf(file,"\n");
  567.         break;
  568.  
  569.         case T_MX:
  570.         if (queryType != T_MX && queryType != T_ANY)
  571.             break;
  572.  
  573.         if ((_res.options & RES_DEBUG) == 0)
  574.             STRIP_DOMAIN(name);
  575.         fprintf(file, NAME_FORMAT, name);
  576.         if (queryType == T_ANY)
  577.             fprintf(file," %-5s", p_type(type));
  578.  
  579.         {
  580.             short pref;
  581.  
  582.             pref = _getshort(cp);
  583.             cp += sizeof(u_short);
  584.             fprintf(file," %-3d ",pref);
  585.         }
  586.         if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
  587.             fprintf(file, " ***\n");
  588.             return (ERROR);
  589.         }
  590.         fprintf(file, " %s", name2);
  591.         if (_res.options & RES_DEBUG)
  592.             fprintf(file,"\t%lu", ttl);
  593.         fprintf(file,"\n");
  594.  
  595.         break;
  596.  
  597.  
  598.         case T_NS:
  599.         case T_PTR:
  600.         if (queryType != T_A && queryType != T_ANY)
  601.             break;
  602.         /*
  603.          *  Found a name server or pointer record.
  604.          */
  605.         if ((_res.options & RES_DEBUG) == 0)
  606.             STRIP_DOMAIN(name);
  607.         fprintf(file, NAME_FORMAT, name);
  608.         if (queryType == T_ANY)
  609.             fprintf(file," %-5s", p_type(type));
  610.         fprintf(file," %s = ", type == T_PTR ? "host" : "server");
  611.         cp = Print_cdname2(cp, msg, eom, file);
  612.         if (_res.options & RES_DEBUG)
  613.             fprintf(file,"\t%lu", ttl);
  614.         fprintf(file,"\n");
  615.         break;
  616.  
  617.         case T_WKS:
  618.         if (queryType != T_WKS && queryType != T_ANY)
  619.             break;
  620.  
  621.         if ((_res.options & RES_DEBUG) == 0)
  622.             STRIP_DOMAIN(name);
  623.         fprintf(file, NAME_FORMAT, name);
  624.         if (queryType == T_ANY)
  625.             fprintf(file," %-5s", p_type(type));
  626.         if (class == C_IN) {
  627.             cp += 4; dlen -= 4;
  628.             {
  629.             struct protoent *pp;
  630.             struct servent *ss;
  631.             u_short port;
  632.  
  633.             setprotoent(1);
  634.             setservent(1);
  635.             n = *cp & 0377;
  636.             pp = getprotobynumber(n);
  637.             if(pp == 0)  
  638.                 fprintf(file," %-3d ", n);
  639.             else
  640.                 fprintf(file," %-3s ", pp->p_name);
  641.             cp++; dlen--;
  642.  
  643.             port = 0;
  644.             while(dlen-- > 0) {
  645.                 n = *cp++;
  646.                 do {
  647.                 if(n & 0200) {
  648.                     ss = getservbyport((int)htons(port), pp->p_name);
  649.                     if(ss == 0)  
  650.                     fprintf(file," %d", port);
  651.                     else
  652.                     fprintf(file," %s", ss->s_name);
  653.                 }
  654.                     n <<= 1;
  655.                 } while(++port & 07);
  656.             }
  657.             } 
  658.         } else
  659.             goto other;
  660.         if (_res.options & RES_DEBUG)
  661.             fprintf(file,"\t%lu", ttl);
  662.         fprintf(file,"\n");
  663.         endprotoent();
  664.         endservent();
  665.         break;
  666.  
  667.         case T_SOA:
  668.         case T_AXFR:
  669.         if (queryType != T_ANY)
  670.             break;
  671.         fprintf(file, NAME_FORMAT, name);
  672.         if (queryType == T_ANY)
  673.             fprintf(file," %-5s", p_type(type));
  674.         if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
  675.             fprintf(file, " ***\n");
  676.             return (ERROR);
  677.         }
  678.         cp += nameLen;
  679.         fprintf(file, " %s", name2);
  680.         if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
  681.             fprintf(file, " ***\n");
  682.             return (ERROR);
  683.         }
  684.         cp += nameLen;
  685.         fprintf(file, " %s. (", name2);
  686.         for (n = 0; n < 5; n++) {
  687.             u_long u;
  688.  
  689.             u = _getlong(cp);
  690.             cp += sizeof(u_long);
  691.             fprintf(file,"%s%d", n? " " : "", u);
  692.         }
  693.         fprintf(file, ")");
  694.         if (_res.options & RES_DEBUG)
  695.             fprintf(file,"\t%lu", ttl);
  696.         fprintf(file,"\n");
  697.         break;
  698.  
  699.         default:
  700.         /*
  701.          * Unwanted answer type -- ignore it.
  702.          */
  703.         if (queryType != T_ANY)
  704.             break;
  705.         if ((_res.options & RES_DEBUG) == 0)
  706.             STRIP_DOMAIN(name);
  707.         fprintf(file, NAME_FORMAT, name);
  708. other:
  709.         fprintf(file," type = %-5s", p_type(type));
  710.         fprintf(file,", class = %-5s", p_class(class));
  711.         if (_res.options & RES_DEBUG)
  712.             fprintf(file,"\t%lu\n", ttl);
  713.         break;
  714.     }
  715.     }
  716.     return(SUCCESS);
  717. }
  718.  
  719.  
  720. /*
  721.  *******************************************************************************
  722.  *
  723.  *  ViewList --
  724.  *
  725.  *    A hack to view the output of the ls command in sorted
  726.  *    order using more.
  727.  *
  728.  *******************************************************************************
  729.  */
  730.  
  731. ViewList(string)
  732.     char *string;
  733. {
  734.     char file[NAME_LEN];
  735.     char command[NAME_LEN];
  736.  
  737.     sscanf(string, " view %s", file);
  738.     (void)sprintf(command, "grep \"^ \" %s | sort | more", file);
  739.     system(command);
  740. }
  741.  
  742. /*
  743.  *******************************************************************************
  744.  *
  745.  *   Finger --
  746.  *
  747.  *    Connects with the finger server for the current host
  748.  *    to request info on the specified person (long form)
  749.  *    who is on the system (short form).
  750.  *
  751.  *  Results:
  752.  *    SUCCESS        the finger server was contacted.
  753.  *    ERROR        the server could not be contacted because 
  754.  *            a socket could not be obtained or connected 
  755.  *            to or the service could not be found.
  756.  *
  757.  *******************************************************************************
  758.  */
  759.  
  760. Finger(string, putToFile)
  761.     char *string;
  762.     int  putToFile;
  763. {
  764.     struct servent         *sp;
  765.     struct sockaddr_in     sin;
  766.     register FILE         *f;
  767.     register int         c;
  768.     register int         lastc;
  769.     char             name[NAME_LEN];
  770.     char             file[NAME_LEN];
  771.  
  772.     /*
  773.      *  We need a valid current host info to get an inet address.
  774.      */
  775.     if (!curHostValid) {
  776.         fprintf(stderr, "Finger: no current host defined.\n");
  777.         return (ERROR);
  778.     }
  779.  
  780.     if (sscanf(string, " finger %s", name) == 1) {
  781.         if (putToFile && (name[0] == '>')) {
  782.         name[0] = '\0';
  783.         }
  784.     } else {
  785.         name[0] = '\0';
  786.     }
  787.  
  788.     sp = getservbyname("finger", "tcp");
  789.     if (sp == 0) {
  790.         fprintf(stderr, "Finger: unknown service\n");
  791.         return (ERROR);
  792.     }
  793.  
  794.     bzero((char *)&sin, sizeof(sin));
  795.     sin.sin_family    = curHostInfo.addrType;
  796.     sin.sin_port    = sp->s_port;
  797.     bcopy(curHostInfo.addrList[0], (char *)&sin.sin_addr, 
  798.         curHostInfo.addrLen);
  799.  
  800.     /*
  801.      *  Set up a virtual circuit to the host.
  802.      */
  803.  
  804.     sockFD = socket(curHostInfo.addrType, SOCK_STREAM, 0);
  805.     if (sockFD < 0) {
  806.         fflush(stdout);
  807.         perror("Finger");
  808.         return (ERROR);
  809.     }
  810.  
  811.     if (connect(sockFD, (char *)&sin, sizeof (sin)) < 0) {
  812.         fflush(stdout);
  813.         perror("Finger");
  814.         close(sockFD);
  815.         sockFD = -1;
  816.         return (ERROR);
  817.     }
  818.  
  819.     if (!putToFile) {
  820.         filePtr = stdout;
  821.     } else {
  822.         filePtr = OpenFile(string, file);
  823.         if (filePtr == NULL) {
  824.         fprintf(stderr, "*** Can't open %s for writing\n", file);
  825.         close(sockFD);
  826.         sockFD = -1;
  827.         return(ERROR);
  828.         }
  829.         fprintf(filePtr,"> %s\n", string);
  830.     }
  831.     fprintf(filePtr, "[%s]\n", curHostInfo.name);
  832.  
  833.     if (name[0] != '\0') {
  834.         write(sockFD, "/W ", 3);
  835.     }
  836.     write(sockFD, name, strlen(name));
  837.     write(sockFD, "\r\n", 2);
  838.     f = fdopen(sockFD, "r");
  839.     while ((c = getc(f)) != EOF) {
  840.         switch(c) {
  841.         case 0210:
  842.         case 0211:
  843.         case 0212:
  844.         case 0214:
  845.             c -= 0200;
  846.             break;
  847.         case 0215:
  848.             c = '\n';
  849.             break;
  850.         }
  851.         putc(lastc = c, filePtr);
  852.     }
  853.     if (lastc != '\n') {
  854.         putc('\n', filePtr);
  855.     }
  856.     putc('\n', filePtr);
  857.  
  858.     close(sockFD);
  859.     sockFD = -1;
  860.  
  861.     if (putToFile) {
  862.         fclose(filePtr);
  863.         filePtr = NULL;
  864.     }
  865.     return (SUCCESS);
  866. }
  867. @
  868.